`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    16:38:29 04/09/2014 
// Design Name: 
// Module Name:    resource_handler 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module controller(
	rx_buffer,
	tx_buffer,
	data_present,
	buffer_full,
	read_strobe,
	write_strobe,
	data_in,
	data_out,
	key,
	clk
);

	input wire [7:0] rx_buffer;
	output reg [7:0] tx_buffer;
	input wire data_present;
	input wire buffer_full;
	output reg read_strobe;
	output reg write_strobe;
	input wire [127:0] data_in;
	output wire [127:0] data_out;
	output wire [127:0] key;
	input wire clk;
	
	reg [7:0] data_out_blocks [15:0];
	wire [7:0] data_in_blocks [15:0];
	reg [127:0] data_in_buffer;
	reg [7:0] key_blocks [15:0];
  
	generate
		genvar i;
		for (i = 0; i < 16; i = i + 1)
		begin: blocks
			assign data_out[(i*8)+7:(i*8)] = data_out_blocks[i];
			assign data_in_blocks[i] = data_in_buffer[(i*8)+7:(i*8)];
			assign key[(i*8)+7:(i*8)] = key_blocks[i];
		end
	endgenerate
	
	reg [5:0] char_in_count = 0;
	reg [4:0] char_out_count = 0;
	reg data_in_sent = 1;	// data_in_buffer has been sent out UART_Tx. data_in can be assigned to data_in_buffer.
	reg send_data_in = 0;	// data_in has been stored in data_in_buffer. send data_in_buffer to UART_Tx.	
	
	// Block for reading in data from UART_Rx and feeding into ICN.
	//	Stores data_in in data_in_buffer after reading 32 chars from UART_Rx (16 key, 16 data)
	always @(negedge clk)
	begin
		if (char_in_count < 32)
		begin
			send_data_in = 1'b0;
			if (data_present)
			begin
				if (char_in_count < 16)
					key_blocks[char_in_count] = rx_buffer;
				else
					data_out_blocks[char_in_count] = rx_buffer;
				data_out_blocks[char_in_count] = rx_buffer;
				read_strobe = 1'b1;
				char_in_count = char_in_count + 1;
			end
			else read_strobe = 1'b0;
		end
		else	// char_in_count should == 32
		begin
			read_strobe = 1'b0;
			if (data_in_sent)
			begin
				data_in_buffer = data_in;
				send_data_in = 1'b1;
				char_in_count = 5'b0;
			end
		end
	end
	
	// Sends 16 chars to UART_Tx after send_data_in goes high
	//	(This means 16 chars have been read in and fed to data_out
	always @(negedge clk)
	begin
		if (send_data_in) data_in_sent = 1'b0;
		
		if (char_out_count < 16)
		begin
			if (!data_in_sent & !buffer_full)
			begin
				tx_buffer = data_in_blocks[char_out_count];
				write_strobe = 1'b1;
				char_out_count = char_out_count + 1;
			end
			else write_strobe = 1'b0;
		end
		else // char_out_count should == 16
		begin
			write_strobe = 1'b0;
			data_in_sent = 1'b1;
			char_out_count = 5'b0;
		end
	end
	
endmodule
